﻿
namespace EasyStep.Business.Managers.FileSystem
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using EasyStep.Business.Interfaces;
    using EasyStep.Data.Entities;
    using System.IO;


    public class TestConstManager : ITestConstantManager
    {
        public const string constFileNamePrefix= "constants.data";
        public const string constFileNameSuffix = ".txt";
        private ITestDataContext Context { get; set; }

        public TestConstManager(ITestDataContext context)
        {
            Context = context;
        }
        public TestConst Get(string name)
        {
            EnsureConstants();
            return Data.Where(i => i.Name.Equals(name, StringComparison.OrdinalIgnoreCase))
                .FirstOrDefault();
        }

        public TestConst GetOrCreateConst(string constNameOrId, string value, Guid constListId, Func<TestConst> onNotFound = null)
        {
            if (constListId!=Guid.Empty)
                throw new NotImplementedException();

            var existing = Get(constNameOrId);
            if (existing == null)
                return Create(new TestConst()
                {
                     Created=DateTime.Now, Name=constNameOrId, Value=value
                });
            return existing;
        }

        public TestConst Create(TestConst item)
        {
            EnsureConstants();
            if (Data.Where(i => i.Name.Equals(item.Name)).FirstOrDefault() != null)
                throw new NotSupportedException("Const Item with same name already exists!" + item.Name);
            Data = Data.Union(new TestConst[] { item });
            UpdateStorage();
            return item;
        }

        public TestConst Update(TestConst item)
        {
            EnsureConstants();
            var existingItem = Data.Where(i => i.Name.Equals(item.Name)).FirstOrDefault();
            if (existingItem == null)
                throw new NotSupportedException("Const Item with same name doesn't exists!" + item.Name);
            existingItem.Value = item.Value;
            UpdateStorage();
            return existingItem;
        }

        public TestConst Delete(TestConst item)
        {
            EnsureConstants();
            var existingItem = Data.Where(i => i.Name.Equals(item.Name)).FirstOrDefault();
            if (existingItem == null)
                throw new NotSupportedException("Const Item with same name doesn't exists!" + item.Name);
            Data = Data.Except(new TestConst[] { existingItem });
            UpdateStorage();
            return existingItem;
        }

        public IEnumerable<TestConst> UpdateAll(IEnumerable<TestConst> toData)
        {
            EnsureConstants();
            Data = toData;
            UpdateStorage();
            return Data;
        }

        #region internal methods
        private IEnumerable<TestConst> Data;
        private string curProject;
        private void EnsureConstants()
        {
            if (Data == null || !Data.Any()|| curProject == null || !curProject.Equals(Context.CurrentProject))
            {
                if (string.IsNullOrEmpty(Context.CurrentProject)) throw (new ArgumentNullException("Test hasn't been chosen!Can't found constants for empty test/project!"));
                curProject = Context.CurrentProject;
                var constsFile = EnsureFile();

                //read data
                List<TestConst> constants = new List<TestConst>();
                using (var fs = File.OpenRead(constsFile))
                using (var tr = new StreamReader(fs))
                    while (!tr.EndOfStream)
                    {
                        var item = Convert(tr.ReadLine() ?? "");
                        if (item != null)
                            constants.Add(item);
                    }
                Data = constants.ToArray();
            }
        }

        private string EnsureFile()
        {
            if (!Directory.Exists(curProject)) Directory.CreateDirectory(curProject);                
            var result = string.IsNullOrEmpty(Context.Environment)
                ? Path.Combine(curProject, string.Concat(constFileNamePrefix,"",constFileNameSuffix))
                : Path.Combine(curProject, string.Concat(constFileNamePrefix,".", Context.Environment, constFileNameSuffix));
            if (!File.Exists(result)) File.WriteAllText(result, "");
            return result;
        }

        private void UpdateStorage()
        {
            var constsFile = EnsureFile();
            //write data
            var sb = new StringBuilder();
            foreach (var item in Data)
            {
                sb.AppendLine(Convert(item));
            }
            File.WriteAllText(constsFile, sb.ToString());
        }
        #endregion

        public TestConst Get(Guid id)
        {
            throw new NotImplementedException();
        }


        public IEnumerable<TestConst> GetAll()
        {
            EnsureConstants();
            return Data;
        }


        public string Convert(TestConst item)
        {        
            if (item==null) return null;
           return string.Format("{0} = {1}",item.Name,item.Value,item.Id,item.ListId);
        }

        public TestConst Convert(string serializedItem)
        {
            if (string.IsNullOrEmpty(serializedItem)) return null;
            var i = serializedItem.IndexOf("=");
            if (i < 0) return null;
            return new TestConst()
            {
                Name = (serializedItem.Substring(0, i)??"").Trim(),
                Value = (serializedItem.Substring(i + 1)??"").Trim()
            };
        }




       
    }
}
